/**
 * @brief token获取类，该类未根据http返回字段expires_in做token缓存
 */

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <curl/curl.h> // 依赖libcurl
#include "token.h"

#include "../../esl/esl_json.h"

const char API_TOKEN_URL[] = "http://openapi.baidu.com/oauth/2.0/token";

const int MAX_TOKEN_SIZE = 100;

const int ENABLE_CURL_VERBOSE = 0;
const int BUFFER_ERROR_SIZE = 1024;
char g_demo_error_msg[1024] = {0};

// libcurl 返回回调
size_t writefunc(void *ptr, size_t size, size_t nmemb, char **result)
{
    size_t result_len = size * nmemb;
    if (*result == NULL)
    {
        *result = (char *)malloc(result_len + 1);
    }
    else
    {
        *result = (char *)realloc(*result, result_len + 1);
    }
    if (*result == NULL)
    {
        printf("realloc failure!\n");
        return 1;
    }
    memcpy(*result, ptr, result_len);
    (*result)[result_len] = '\0';
    // printf("buffer: %s\n", *result);
    return result_len;
}

// 解析response json ， 获取token，验证scope信息
RETURN_CODE
speech_get_token(const char *api_key, const char *secret_key, const char *scope, char *token)
{
    char url_pattern[] = "%s?grant_type=client_credentials&client_id=%s&client_secret=%s";
    char url[200];
    char *response = NULL;

    snprintf(url, 200, url_pattern, API_TOKEN_URL, api_key, secret_key);
    printf("url is: %s\n", url);
    CURL *curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, url); // 注意返回值判读
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60); // 60s超时
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, ENABLE_CURL_VERBOSE);
    CURLcode res_curl = curl_easy_perform(curl);
    RETURN_CODE res = RETURN_OK;
    if (res_curl != CURLE_OK)
    {
        snprintf(g_demo_error_msg, BUFFER_ERROR_SIZE, "perform curl error:%d, %s.\n", res,
                 curl_easy_strerror(res_curl));
        res = ERROR_TOKEN_CURL;
    }
    else
    {
        res = parse_token(response, scope, token); // 解析token，结果保存在token里
        if (res == RETURN_OK)
        {
            printf("token: %s of %s\n", token, response);
        }
    }
    free(response);
    curl_easy_cleanup(curl);
    return res;
}

// 解析json，获取某个key对应的value ;为了不引用第三方json库，仅仅做简单的字符串操作
// 正式使用请使用json库解析，json库解析推荐@see www.json.org
RETURN_CODE parse_token(const char *response, const char *scope, char *token)
{
    //  ====  获取 token字段 =========
    RETURN_CODE res = obtain_json_str(response, "access_token", token, MAX_TOKEN_SIZE);

    if (res != RETURN_OK)
    {
        snprintf(g_demo_error_msg, BUFFER_ERROR_SIZE, "parse token error: %s\n", response);
        return ERROR_TOKEN_PARSE_ACCESS_TOKEN;
    }

    // ==== 检查scope =========
    char scopes[1200] = {0};
    res = obtain_json_str(response, "scope", scopes, 300);
    if (res != RETURN_OK)
    {
        snprintf(g_demo_error_msg, BUFFER_ERROR_SIZE, "parse scope error: %s\n", response);
        return ERROR_TOKEN_PARSE_ACCESS_TOKEN;
    }
    char *scope_pos = strstr(scopes, scope);
    if (scope_pos == NULL)
    {
        snprintf(g_demo_error_msg, BUFFER_ERROR_SIZE, "scope： %s not exist in:%s \n", scope,
                 response);
        return ERROR_TOKEN_PARSE_SCOPE;
    }
    return RETURN_OK;
}

RETURN_CODE obtain_json_str(const char *json, const char *key, char *value, int value_size)
{

    cJSON *item = NULL;

    cJSON *root = cJSON_Parse(json);

    if (root == NULL)
    {
        printf("%s key not exist\n", key);
        return RETURN_ERROR;
    }

    item = cJSON_GetObjectItem(root, key);
    sprintf(value, "%s", cJSON_Print(item));
    return RETURN_OK;
}

// {
//   "log_id": 3705170276338818927,
//   "text": "我不想要",
//   "items": [
//     {
//       "positive_prob": 0.387384,
//       "sentiment": 0,
//       "confidence": 0.139147,
//       "negative_prob": 0.612616
//     }
//   ]
// }

RETURN_CODE parse_positive_prob(const char *json, const char *key, char *value, int value_size)
{
    cJSON *items = NULL;

    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        printf("%s key not exist\n", key);
        return RETURN_ERROR;
    }
    items = cJSON_GetObjectItem(root, "items");
    int array_size = cJSON_GetArraySize(items);
    printf("array size is %d\n", array_size);
    int i = 0;
    cJSON *item;

    for (i = 0; i < array_size; i++)
    {
        item = cJSON_GetArrayItem(items, i);
        sprintf(value, "%s", cJSON_Print(cJSON_GetObjectItem(item, key)));
    }

    if (root)
        cJSON_Delete(root);
    return RETURN_OK;
}
RETURN_CODE parse_ali_asr(const char *json, const char *key, char *value, int value_size)
{
    cJSON *items = NULL;

    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        printf("%s key not exist\n", key);
        return RETURN_ERROR;
    }
    items = cJSON_GetObjectItem(root, "result");
    sprintf(value, "%s", cJSON_Print(cJSON_GetObjectItem(items, key)));

    if (root)
        cJSON_Delete(root);
    return RETURN_OK;
}
